
#include "Environment.h"

#include <stdio.h>
#include <iostream>
#include "Locker.h"
#include "Agent.h"

using namespace std;

Environment::Environment() {
    resetBoard();
}

Environment::~Environment() {
    deleteBoard();
}

void Environment::printBoard() {
    EnvCell* tmpCell;
    cout << endl;
    for (int row = 0; row < BOARD_ROWS; row++) {
        for (int col = 0; col < BOARD_COLUMNS; col++) {
            tmpCell = m_ParticleBoard[row][col];
            cout << tmpCell->getNumParticles();
            for(int i = 0; i < tmpCell->agentsPresent(); i++){
                cout << "*";
            }
          
                cout << " ";
           
            if (col == BOARD_COLUMNS - 1) {
                cout << endl;
            }
        }
    }
}

void Environment::cleanBoard() {
    EnvCell* tmpCell;
    for (int row = 0; row < BOARD_ROWS; row++) {
        for (int col = 0; col < BOARD_COLUMNS; col++) {
            tmpCell = m_ParticleBoard[row][col];
            tmpCell->cleanCell();
        }
    }
}

void Environment::deleteBoard() {
    cleanBoard();
    for (int row = 0; row < BOARD_ROWS; row++) {
        for (int col = 0; col < BOARD_COLUMNS; col++) {
            delete m_ParticleBoard[row][col];
        }
    }
}

//ToDo: Add agents into reset

bool Environment::resetBoard() {
    if (m_ParticleBoard.size() != 0) {
        deleteBoard();
    }

    int particleID = 1;
    EnvCell* tmpCell;
    Particle* newParticle;

    //resize board to proper rows and columns
    m_ParticleBoard.resize(BOARD_ROWS);
    for (int row = 0; row < BOARD_ROWS; row++) {
        m_ParticleBoard[row].resize(BOARD_COLUMNS);
    }

    //initialize each cell of the board
    //first row contains all the starting particles
    for (int row = 0; row < BOARD_ROWS; row++) {
        for (int col = 0; col < BOARD_COLUMNS; col++) {
            tmpCell = new EnvCell();
            if (row == 0) {
                for (int count = 0; count < NUM_STARTING_PARTICLES_PER_CELL; count++) {
                    newParticle = new Particle(particleID);
                    tmpCell->placeParticle(newParticle);
                    particleID++;
                }
            }
            m_ParticleBoard[row][col] = tmpCell;
        }
    }
}

bool Environment::accountParticles() {

    vector<int> assignedIDs;
    EnvCell* tmpCell;
    
    for (int count = 1; count <= TOTAL_STARTING_PARTICLES; count++) {
        assignedIDs.push_back(count);
    }

    for (int row = 0; row < BOARD_ROWS; row++) {
        for (int col = 0; col < BOARD_COLUMNS; col++) {
            tmpCell = m_ParticleBoard[row][col];
            assignedIDs = tmpCell->accountCell(assignedIDs);
        }
    }
    if (assignedIDs.size() == 0) {
        return true;
    } else {
        return false;
    }
}

EnvCell* Environment::getCell(int row, int col) {
    if ((row < 0) || (row >= BOARD_ROWS) || (col < 0) || (col >= BOARD_COLUMNS)) {
        printf("Enviroment::getCell ERROR: row or col out of range\n");
        return NULL;
    } else {
        EnvCell* tmpCell = m_ParticleBoard[row][col];
        return tmpCell;
    }
}

int Environment::countParticles(){
    EnvCell* tmpCell;
    int particleCount = 0;
    for (int row = 0; row < BOARD_ROWS; row++) {
        for (int col = 0; col < BOARD_COLUMNS; col++) {
            tmpCell = m_ParticleBoard[row][col];
            particleCount += tmpCell->getNumParticles();
        }
    }
    return particleCount;
}

std::vector<std::vector<EnvCell*> > Environment::m_ParticleBoard;